
package com.hangzhou.xyj.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.ExifInterface;
import android.os.Build.VERSION;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.util.Log;
import android.widget.ImageView;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Bitmap工具类
 */
public class BitmapUtils {

    // 存储大小1GB
    public static final long GB = 1073741824;
    // 存储大小1MB
    public static final long MB = 1048576;
    // 存储大小1KB
    public static final long KB = 1024;
    // jpg文件后缀名
    public final static String SUFFIX_JPG = ".jpg";
    // png文件后缀名
    public final static String SUFFIX_PNG = ".png";
    // jpeg文件后缀名
    public final static String SUFFIX_JPEG = ".jpeg";
    private final static String TAG = BitmapUtils.class.getSimpleName();

    /**
     * RGB_565
     *
     * @return
     */
    public static Bitmap.Config getRGBConfig() {
        return Bitmap.Config.RGB_565;
    }

    /**
     * 画圆形图片
     *
     * @param bitmap 输入的图片bitmap
     * @param pixels 圆形弧度
     * @return
     */
    public static Bitmap toRoundCorner(Bitmap bitmap, float pixels) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), getRGBConfig());
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);
        final float roundPx = pixels;

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);

        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;
    }

    /**
     * 用于生成缩略图,压缩成二进制数组 限制32KB
     *
     * @param bmp
     * @param needRecycle
     * @return
     */
    public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int quality = 100;
        while (baos.toByteArray().length / KB > 32) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();// 重置baos即清空baos
            bmp.compress(Bitmap.CompressFormat.JPEG, quality, baos);// 这里压缩options%，把压缩后的数据存放到baos中
            quality -= 5;// 每次都减少5
        }

        if (needRecycle) {
            bmp.recycle();
        }

        byte[] result = baos.toByteArray();
        try {
            baos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    public static byte[] bmpToByteArray1(final Bitmap bmp, final boolean needRecycle) {
        int i;
        int j;
        if (bmp.getHeight() > bmp.getWidth()) {
            i = bmp.getWidth();
            j = bmp.getWidth();
        } else {
            i = bmp.getHeight();
            j = bmp.getHeight();
        }

        int innerLoop = 0, outerLoop = 0;
        Bitmap localBitmap = Bitmap.createBitmap(i, j, getRGBConfig());
        Canvas localCanvas = new Canvas(localBitmap);

        while (true) {
            outerLoop++;
            localCanvas.drawBitmap(bmp, new Rect(0, 0, i, j), new Rect(0, 0, i, j), null);
            if (needRecycle)
                bmp.recycle();

            int quality = 100;
            ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();
            byte[] arrayOfByte = null;

            do {
                innerLoop++;
                localByteArrayOutputStream.reset();// 重置baos即清空baos
                localBitmap.compress(Bitmap.CompressFormat.JPEG, quality, localByteArrayOutputStream);
                arrayOfByte = localByteArrayOutputStream.toByteArray();
                quality -= 5;// 每次都减少5
            } while (arrayOfByte.length / KB > 32);

            localBitmap.recycle();
            try {
                localByteArrayOutputStream.close();
                LogUtil.i(TAG, "innerLoop:" + innerLoop + " outerLoop:" + outerLoop);
                return arrayOfByte;
            } catch (Exception e) {
                //F.out(e);
            }
            i = bmp.getHeight();
            j = bmp.getHeight();
        }
    }


    public static Bitmap smallBitmap(Bitmap bitmap, int dstWidth) {
        Matrix matrix = new Matrix();
        int width = bitmap.getWidth();
        if (dstWidth > width)
            return bitmap;
        float scale = dstWidth / (float) width;
        matrix.postScale(scale, scale); //长和宽放大缩小的比例
        Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return resizeBmp;
    }


    /**
     * 图片拉伸
     *
     * @param bm
     * @param dstWidth
     * @param dstHeight
     * @return
     */
    public static Bitmap scaleBitmap(Bitmap bm, int dstWidth, int dstHeight) {
        Bitmap outBm = Bitmap.createBitmap(dstWidth, dstHeight, getRGBConfig());
        Canvas canvas = new Canvas(outBm);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        int width = bm.getWidth(), height = bm.getHeight();
        int left = 0, top = 0;
        if (width > dstWidth) {
            left = (width - dstWidth) / 2;
        } else {
            width = dstWidth;
        }
        if (height > dstHeight) {
            top = (height - dstHeight) / 2;
        } else {
            height = dstHeight;
        }
        Rect rect = new Rect(left, top, left + dstWidth, top + dstHeight);
        Rect bmRect = new Rect(0, 0, width, height);
        canvas.save();
        canvas.drawBitmap(bm, null, bmRect, paint);
        canvas.clipRect(rect);
        canvas.restore();
        return outBm;
    }

    /**
     * 压缩图片
     *
     * @params image 图片Bitmap对象
     */
    public static Bitmap compressImage(Bitmap image) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int quality = 100;
        while (baos.toByteArray().length / MB > 2) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();// 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, quality, baos);// 这里压缩options%，把压缩后的数据存放到baos中
            quality -= 5;// 每次都减少5
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    /**
     * 压缩图片
     *
     * @params input 输入的图片路径
     * @params output 输出的图片路径
     */
    public static boolean compressImage(String input, String output) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        int sampleSize = 100;
        opts.inSampleSize = sampleSize;
        Bitmap inImage = BitmapFactory.decodeFile(input, opts);
        return true;
    }

    /**
     * 获取图片信息，主要是宽，高和大小
     *
     * @param input
     * @return int[] [0] 宽|[1] 高 |[2] 文件大小
     */
    @Deprecated
    public static int[] getImageInfo(String input) {

        int[] values = new int[3];
        Bitmap inImage = null;
        try {
            File f = new File(input);
            if (f.exists()) {
                BitmapFactory.Options opts = new BitmapFactory.Options();
                opts.inJustDecodeBounds = true;
                inImage = BitmapFactory.decodeFile(f.getAbsolutePath(), opts);
                values[0] = opts.outWidth;
                values[1] = opts.outHeight;
                values[2] = (int) f.length();
            }
        } catch (Exception e) {
            Log.e(TAG, ">>>>>> getImageWH.error:" + e.getMessage());
        } finally {
            if (null != inImage && !inImage.isRecycled()) {
                inImage.recycle();
                System.gc();
            }
        }
        return values;

    }


    /**
     * 保存位图
     *
     * @param bitmap
     * @param path
     * @return
     */
    public static void saveBitmap(Bitmap bitmap, String path, CompressFormat format) {
        if (bitmap == null || StringUtil.isEmpty(path)) return;
        FileOutputStream fileOut = null;

        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            if (format == null) {
                if (path.endsWith(SUFFIX_PNG)) {
                    format = CompressFormat.PNG;
                } else if (path.endsWith(SUFFIX_JPG) || path.endsWith(SUFFIX_JPEG)) {
                    format = CompressFormat.JPEG;
                } else {
                    format = CompressFormat.PNG;
                }
            }
            bitmap.compress(format, 100, byteOut);
            byte[] buffer = byteOut.toByteArray();

            fileOut = new FileOutputStream(path);
            fileOut.write(buffer, 0, buffer.length);
            fileOut.flush();
        } catch (Exception ex) {
        } finally {
            try {
                if (fileOut != null) fileOut.close();
            } catch (Exception ex) {
            }
        }
    }


    /**
     * 柔化效果(高斯模糊)(优化后比上面快三倍)
     *
     * @param bmp
     * @return
     */
    public static Bitmap blurImageAmeliorate(Bitmap bmp) {
        // 高斯矩阵
        int[] gauss = new int[]{1, 2, 1, 2, 4, 2, 1, 2, 1};

        int width = bmp.getWidth();
        int height = bmp.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, getRGBConfig());

        int pixR = 0;
        int pixG = 0;
        int pixB = 0;

        int pixColor = 0;

        int newR = 0;
        int newG = 0;
        int newB = 0;

        int delta = 16; // 值越小图片会越亮，越大则越暗

        int idx = 0;
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 1, length = height - 1; i < length; i++) {
            for (int k = 1, len = width - 1; k < len; k++) {
                idx = 0;
                for (int m = -1; m <= 1; m++) {
                    for (int n = -1; n <= 1; n++) {
                        pixColor = pixels[(i + m) * width + k + n];
                        pixR = Color.red(pixColor);
                        pixG = Color.green(pixColor);
                        pixB = Color.blue(pixColor);

                        newR = newR + pixR * gauss[idx];
                        newG = newG + pixG * gauss[idx];
                        newB = newB + pixB * gauss[idx];
                        idx++;
                    }
                }

                newR /= delta;
                newG /= delta;
                newB /= delta;

                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));

                pixels[i * width + k] = Color.argb(255, newR, newG, newB);

                newR = 0;
                newG = 0;
                newB = 0;
            }
        }

        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 读取图片的旋转的角度
     *
     * @param path 图片绝对路径
     * @return 图片的旋转角度:0 or 90 or 180 or 270
     */
    public static int getBitmapDegree(String path) {
        int degree = 0;
        try {
            // 从指定路径下读取图片，并获取其EXIF信息
            ExifInterface exifInterface = new ExifInterface(path);
            // 获取图片的旋转信息
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);

            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 将图片按照某个角度进行旋转
     *
     * @param bm     需要旋转的图片
     * @param degree 旋转角度
     * @return 旋转后的图片
     */
    public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
        if (bm == null) {
            return null;
        }
        Bitmap returnBm = null;

        // 根据旋转角度，生成旋转矩阵
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);


        try {
            if (!bm.isRecycled()) {
                // 将原始图片按照旋转矩阵进行旋转，并得到新的图片
                returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
            }
        } catch (Throwable th) {
            LogUtil.e("BitmapUtils", "rotateBitmapByDegree rotate bitmap errors.", th);
        }
        if (returnBm == null) {
            returnBm = bm;
        }
        if (bm != returnBm) {
            bm.recycle();
        }
        return returnBm;
    }

    //	设置图片毛玻璃效果
    public void setBlueImage(Bitmap loadedImage, ImageView destimgview, Context cxt) {
        if (cxt == null) return;
        if (VERSION.SDK_INT > 16) {
            final float radius = 16.0f;

            Bitmap bitmap = loadedImage.copy(loadedImage.getConfig(), true);
            final RenderScript rs = RenderScript.create(cxt);
            final Allocation input = Allocation.createFromBitmap(rs, loadedImage, Allocation.MipmapControl.MIPMAP_NONE,
                    Allocation.USAGE_SCRIPT);
            final Allocation output = Allocation.createTyped(rs, input.getType());
            final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
            script.setRadius(radius /* e.g. 3.f */);
            script.setInput(input);
            script.forEach(output);
            output.copyTo(bitmap);

//            Bitmap darkbitmap = bitmap.copy(bitmap.getConfig(), true);
//
//            float brightness  = -42;//亮度(N取值为-255到255)
//            ColorMatrix cMatrix = new ColorMatrix();
//            cMatrix.set(new float[] { 1, 0, 0, 0, brightness, 0, 1,
//                    0, 0, brightness,// 改变亮度
//                    0, 0, 1, 0, brightness, 0, 0, 0, 1, 0 });  
//            
//            Paint paint = new Paint();  
//            paint.setColorFilter(new ColorMatrixColorFilter(cMatrix));  
//            
//            Canvas canvas = new Canvas(darkbitmap);  
//            canvas.drawBitmap(bitmap, 0, 0, paint);  

            destimgview.setImageBitmap(bitmap);
        }
    }
}
